package com.qfedu.microlottery.award.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qfedu.common.core.entity.Lotteryactivity;
import com.qfedu.common.core.entity.Lotteryaward;
import com.qfedu.common.core.entity.Lotteryrecord;
import com.qfedu.common.core.exception.CommonException;
import com.qfedu.common.core.utils.UserUtils;
import com.qfedu.common.mq.utils.RocketMqUtils;
import com.qfedu.common.redis.utils.RedisCache;
import com.qfedu.microlottery.activity.service.LotteryactivityService;
import com.qfedu.microlottery.award.mapper.LotteryawardMapper;
import com.qfedu.microlottery.award.service.LotteryawardService;
import com.qfedu.microlottery.record.service.LotteryrecordService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @Classname LotteryawardServiceImpl
 * @Description TODO
 * @Date 2025-10-09 11:04
 * @Created by 老任与码
 */
@Service
public class LotteryawardServiceImpl implements LotteryawardService {

    @Resource
    private LotteryawardMapper lotteryawardMapper;

    @Resource
    private LotteryactivityService lotteryactivityService;

    @Resource
    private LotteryrecordService lotteryrecordService;

    @Resource
    private RedisCache redisCache;

    @Resource
    private RocketMqUtils rocketMqUtils;

    @Override
    public int lottery(Integer activityId) {
        // 抽奖业务中要进行多种判断，比如活动是否开始或者结束，当天是否达到抽奖次数的上限....
        Lotteryactivity lotteryactivity = lotteryactivityService.activityInfo(activityId);
        Date now = new Date();
        if (lotteryactivity == null || lotteryactivity.getStartTime().after(now) || lotteryactivity.getEndTime().before(now)) {
            throw new CommonException("抽奖活动未开始或已结束");
        }
        Integer uid = UserUtils.getUid();
        // 当天是否达到抽奖次数的上限
        int count = lotteryrecordService.totalRecordCount(uid, lotteryactivity.getId());
        if (count == lotteryactivity.getNum()) {
            throw new CommonException("今日抽奖已达上限");
        }
        // 生成抽奖分布数组
        Integer[] awardArray = createAwardArray(activityId);

        // 生成随机值，进行抽奖
        int index = RandomUtil.randomInt(128);
        Integer awardId = awardArray[index];
        if (awardId.equals(0)) {
            Lotteryrecord lotteryrecord = new Lotteryrecord();
            lotteryrecord.setActivityId(activityId);
            lotteryrecord.setUid(uid);
            lotteryrecord.setAwardId(0);
            // 发送消息
            rocketMqUtils.sendSyncMsg("lottery_topic", null, JSON.toJSONString(lotteryrecord));
            // lotteryrecordService.addRecord(lotteryrecord);
            throw new CommonException("谢谢惠顾");
        }

        // 判断奖品是否还有剩余
        Lotteryaward lotteryaward = lotteryawardMapper.selectById(awardId);
        if (lotteryaward.getNum().equals(0)) {
            Lotteryrecord lotteryrecord = new Lotteryrecord();
            lotteryrecord.setActivityId(activityId);
            lotteryrecord.setUid(uid);
            lotteryrecord.setAwardId(0);

            rocketMqUtils.sendSyncMsg("lottery_topic", null, JSON.toJSONString(lotteryrecord));
            // lotteryrecordService.addRecord(lotteryrecord);
            throw new CommonException("谢谢惠顾");
        }

        // 修改奖品的剩余个数
        lotteryawardMapper.update(null, Wrappers.lambdaUpdate(Lotteryaward.class)
                .set(Lotteryaward::getNum, lotteryaward.getNum() - 1)
                .eq(Lotteryaward::getId, awardId));

        // 生成抽奖记录
//        Lotteryrecord lotteryrecord = new Lotteryrecord();
//        lotteryrecord.setActivityId(activityId);
//        lotteryrecord.setUid(uid);
//        lotteryrecord.setAwardId(awardId);

        
        // 通过建造者模式创建对象
        Lotteryrecord lotteryrecord =
                new Lotteryrecord.RecordBuilder().uid(uid).activityId(activityId).awardId(awardId).build();

        rocketMqUtils.sendSyncMsg("lottery_topic", null, JSON.toJSONString(lotteryrecord));
        // lotteryrecordService.addRecord(lotteryrecord);

        return awardId;

    }

    /**
     * 根据奖品生成奖品分布的数组
     */
    private Integer[] createAwardArray(Integer activityId) {
        // 从redis中取，如果没有，查询数据库，将奖项分布数组存入redis
        List<Integer> awardsList = redisCache.getCacheObject("lottery:activity:" + activityId);
        Integer[] awards = new Integer[128];
        if (awardsList == null) {
            // 针对可能存在的多线程并发情况，可以考虑加锁
            synchronized (LotteryawardServiceImpl.class) {
                List<Integer> temp = redisCache.getCacheObject("lottery:activity:" + activityId);
                if (temp != null) {
                    awardsList.toArray(awards);
                    return awards;
                }
                List<Lotteryaward> lotteryawards = lotteryawardMapper.selectList(Wrappers.lambdaQuery(Lotteryaward.class)
                        .eq(Lotteryaward::getActivityId, activityId));
                int num = 0;
                for (Lotteryaward award : lotteryawards) {
                    BigDecimal percent = award.getPercent();
                    // java中BigDecimal调用方法进行运算，本例multiply()表示乘法
                    int count = percent.multiply(new BigDecimal("100")).intValue();
                    for (int i = num; i < 100; i++) {
                        if (i == count + num) {
                            num += count;
                            break;
                        }
                        int hashCode = i * 0x61c88647 + 0x61c88647;
                        int index = hashCode & (128 - 1);
                        System.out.println(index);
                        awards[index] = award.getId();
                    }

                }
                for (int i = 0; i < 127; i++) {
                    if (awards[i] == null) {
                        awards[i] = 0;
                    }
                }
                // 存入redis
                List<Integer> list = Arrays.asList(awards);
                redisCache.setCacheObject("lottery:activity:" + activityId, list);
            }

        } else {
            awardsList.toArray(awards);
        }

        return awards;
    }
}
